#include "CylinderShape.h"

#include <cmath>

CylinderShape::CylinderShape(Point poisition, float radius, float thickness) {
	this->position->from(poisition);
	this->radius = radius;
	this->thickness = thickness;
}

void CylinderShape::init() {
	int SEGMENTS = 51;
	this->points = new Point[SEGMENTS * 2];

	int index = 0;
	for (int i = 0; i < SEGMENTS; i++) {
		float currentSegment = (float)i / (float)SEGMENTS;
		float xPos = std::cos(currentSegment * 2.0f * M_PI);
		float yPos = std::sin(currentSegment * 2.0f * M_PI);
		float zPos = thickness / 2;
		this->points[index++] = Point(xPos * radius, yPos * radius, zPos);
	}

	for (int i = 0; i < SEGMENTS; i++) {
		float currentSegment = (float)i / (float)SEGMENTS;
		float xPos = std::cos(currentSegment * 2.0f * M_PI);
		float yPos = std::sin(currentSegment * 2.0f * M_PI);
		float zPos = -thickness / 2;
		this->points[index++] = Point(xPos * radius, yPos * radius, zPos);
	}

	this->vertexSize = SEGMENTS * 24;
	this->vertex = new float[this->vertexSize];
	index = 0;
	for (int i = 0; i < SEGMENTS; i++) {
		this->vertex[index++] = this->points[i].x(); // x position
		this->vertex[index++] = this->points[i].y(); // y position
		this->vertex[index++] = this->points[i].z(); // z position
		Point normal = Point(0, 0, 1);
		normal.normalize();
		this->vertex[index++] = normal.x();
		this->vertex[index++] = normal.y();
		this->vertex[index++] = normal.z();
	}

	for (int i = 0; i < SEGMENTS; i++) {
		this->vertex[index++] = this->points[SEGMENTS + i].x(); // x position
		this->vertex[index++] = this->points[SEGMENTS + i].y(); // y position
		this->vertex[index++] = this->points[SEGMENTS + i].z(); // z position
		Point normal = Point(0, 0, -1);
		normal.normalize();
		this->vertex[index++] = normal.x();
		this->vertex[index++] = normal.y();
		this->vertex[index++] = normal.z();
	}

	for (int i = 0; i < SEGMENTS; i++) {
		this->vertex[index++] = this->points[i].x(); // x position
		this->vertex[index++] = this->points[i].y(); // y position
		this->vertex[index++] = this->points[i].z(); // z position
		Point normal = Point(this->points[i].x(), this->points[i].y(), 0);
		normal.normalize();
		this->vertex[index++] = normal.x();
		this->vertex[index++] = normal.y();
		this->vertex[index++] = normal.z();
	}

	for (int i = 0; i < SEGMENTS; i++) {
		this->vertex[index++] = this->points[SEGMENTS + i].x(); // x position
		this->vertex[index++] = this->points[SEGMENTS + i].y(); // y position
		this->vertex[index++] = this->points[SEGMENTS + i].z(); // z position
		Point normal = Point(this->points[SEGMENTS + i].x(), this->points[SEGMENTS + i].y(), 0);
		normal.normalize();
		this->vertex[index++] = normal.x();
		this->vertex[index++] = normal.y();
		this->vertex[index++] = normal.z();
	}


	this->vbo->create();
	this->vbo->bind();
	this->vbo->allocate(this->getVertex(), this->getVertexSize() * sizeof(float));
	this->vbo->release();

	this->indexSize = (SEGMENTS - 2) * 6 + (SEGMENTS) * 6;
	this->indexes = new unsigned int[this->indexSize];
	//indies
	index = 0;
	for (int i = 0; i < SEGMENTS - 2; i++) {
		this->indexes[index++] = 0; // top circle
		this->indexes[index++] = i + 1; // top circle
		this->indexes[index++] = i + 2 == SEGMENTS ? 0 : i + 2; // top circle

		this->indexes[index++] = SEGMENTS + i + 2 == SEGMENTS ? SEGMENTS : SEGMENTS + i + 2; // bottom circle
		this->indexes[index++] = SEGMENTS + i + 1; // bottom circle
		this->indexes[index++] = SEGMENTS; // bottom circle
	}

	for (int i = 0; i < SEGMENTS; i++) {
		this->indexes[index++] = 2 * SEGMENTS + i; // top circle
		this->indexes[index++] = 3 * SEGMENTS + i; // bottom circle
		this->indexes[index++] = 2 * SEGMENTS + i + 1 == 3 * SEGMENTS ? 2 * SEGMENTS : 2 * SEGMENTS + i + 1; // top circle

		this->indexes[index++] = 3 * SEGMENTS + i; // bottom circle
		this->indexes[index++] = 3 * SEGMENTS + i + 1 == 4 * SEGMENTS ? 3 * SEGMENTS : 3 * SEGMENTS + i + 1;
		this->indexes[index++] = 2 * SEGMENTS + i + 1 == 3 * SEGMENTS ? 2 * SEGMENTS : 2 * SEGMENTS + i + 1; // top circle
	}

	this->ebo->create();
	this->ebo->bind();
	this->ebo->allocate(this->getIndexes(), this->getIndexSize() * sizeof(unsigned int));
	this->ebo->release();

}